package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.commom.constants.articlle.ArticleConstants;
import com.heima.common.exception.CustException;
import com.heima.feigns.AdminFeign;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vo.HotArticleVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class HotArticleServiceImpl implements HotArticleService {

    @Autowired
    ApArticleMapper apArticleMapper;

    @Autowired
    AdminFeign adminFeign;

    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * 计算热文章
     */
    @Override
    public void computeHotArticle() {
        //1 查询前5天的 （已上架、未删除） 文章数据
        String date = LocalDateTime.now().minusDays(5)
                .format(DateTimeFormatter.ofPattern("yyyy-MM-dd 00:00:00"));
        List<ApArticle> apArticles = apArticleMapper.selectArticleByDate(date);
        //2 计算热点文章分值
        List<HotArticleVo> hotArticleVos = apArticles.stream().map(apArticle -> {
            HotArticleVo hotArticleVo = new HotArticleVo();
            BeanUtils.copyProperties(apArticle, hotArticleVo);
            // 计算每个文章的分值
            Integer score = getScore(hotArticleVo);
            hotArticleVo.setScore(score);
            return hotArticleVo;
        }).collect(Collectors.toList());
        //3 为每一个频道缓存热点较高的30条文章
        // 获取到 所有的频道信息
        ResponseResult<List<AdChannel>> listResponseResult = adminFeign.selectChannels();
        if(!listResponseResult.checkCode()){
            CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR);
        }
        List<AdChannel> adChannelList = listResponseResult.getData();
        // 根据 根据频道id 进行分组 过滤 将对应的文章 存入redis中
        // 循环遍历 频道信息
        for (AdChannel adChannel : adChannelList) {
            List<HotArticleVo> hotArticleVoList = hotArticleVos.stream().filter(hotArticleVo -> hotArticleVo.getChannelId().equals(adChannel.getId()))
                    .collect(Collectors.toList());
            //将频道内的文章按照 分值降序 排序 取前三十个
            extracted(ArticleConstants.HOT_ARTICLE_FIRST_PAGE+adChannel.getId(), hotArticleVoList);
        }
        // 文章推介页展示 所有频道的总文章按照分值取最高的前30
        extracted(ArticleConstants.DEFAULT_TAG,hotArticleVos);

    }
    //根据频道 将 将文章按照得分值 降序排序 取前30 存入redis中
    private void extracted(String cacheKey, List<HotArticleVo> hotArticleVoList) {
        List<HotArticleVo> articleVos = hotArticleVoList.stream()
                .sorted(Comparator.comparing(HotArticleVo::getScore).reversed())
                .limit(30)
                .collect(Collectors.toList());
        redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(articleVos));
    }

    private Integer getScore(HotArticleVo hotArticleVo){
        Integer score = hotArticleVo.getScore();
        score = 0;
        // 获取到 文章的阅读数量 收藏数量 评论数量 点赞数量
        Integer views = hotArticleVo.getViews();
        Integer collection = hotArticleVo.getCollection();
        Integer comment = hotArticleVo.getComment();
        Integer likes = hotArticleVo.getLikes();
        if(views != null){
            score +=  views * ArticleConstants.HOT_ARTICLE_VIEW_WEIGHT;
        }
        if(collection != null){
            score += collection * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        if(comment != null){
            score += comment * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        if(likes != null){
            score += likes * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        return score;
    }
}
